package com.tianyu.inspection.common;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author swyan
 */

public class ObjectModel {
    public static Pattern patternLineToHump = Pattern.compile("_(\\w)");
    public static Pattern patternHumpToLine = Pattern.compile("[A-Z]");

    /**
     * 实体类转Map对象
     *
     * @param entity 实体类
     * @return 实体类转化为的Map对象
     */
    public static Map<String, Object> entityToMap(Object entity) {
        if (Objects.isNull(entity)) {
            return null;
        }
        Map<String, Object> entityMap = new HashMap<>(15);
        Field[] declaredFields = entity.getClass().getDeclaredFields();
        for (Field item : declaredFields) {
            item.setAccessible(true);
            try {
                if (Objects.nonNull(item.get(entity))) {
                    entityMap.put(item.getName(), item.get(entity));
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return entityMap;
    }

    /**
     * 实体类转Map对象
     *
     * @param entity 实体类
     * @return 实体类转化为的Map对象
     */
    public static Map<String, Object> entityToLineKeyMap(Object entity) {
        if (Objects.isNull(entity)) {
            return null;
        }
        Map<String, Object> entityMap = new HashMap<>(15);
        Field[] declaredFields = entity.getClass().getDeclaredFields();
        for (Field item : declaredFields) {
            item.setAccessible(true);
            try {
                if (Objects.nonNull(item.get(entity))) {
                    entityMap.put(humpToLine(item.getName()), item.get(entity));
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return entityMap;
    }

    /**
     * 字符串转Map对象
     *
     * @param string 字符串
     * @return Map对象
     */
    public static HashMap<String, Object> stringToMap(String string) {
        HashMap<String, Object> map = new HashMap<>(10);
        String emptyString = "{}";
        if (emptyString.equals(string)) {
            return map;
        }
        boolean isJsonString = string.startsWith("\"") && string.endsWith("\"");
        if (isJsonString) {
            map.put("error", "非法字符串");
            return map;
        }
        string = string.substring(1, string.length() - 1);
        String[] keyValues = string.split(",");
        for (String item : keyValues) {
            String[] split = item.split(":");
            String key = split[0];
            String value = split[1];
            boolean keyFlag = key.startsWith("\"") && key.endsWith("\"");
            if (keyFlag) {
                key = key.substring(1, key.length() - 1);
            }
            boolean valueFlag = value.startsWith("\"") && value.endsWith("\"");
            if (valueFlag) {
                value = value.substring(1, value.length() - 1);
                map.put(key, value);
            } else {
                if ("null".equals(value)) {
                    map.put(key, null);
                } else if ("true".equals(value) || "false".equals(value)) {
                    boolean b = Boolean.parseBoolean(value);
                    map.put(key, b);
                } else {
                    Number number = Long.parseLong(value);
                    map.put(key, number);
                }
            }
        }
        return map;
    }

    public static JSONObject getLineKeyMap(Map<String, Object> map) {
        JSONObject modelMap = new JSONObject();
        if (Objects.nonNull(map)) {
            Set<String> strings = map.keySet();
            strings.forEach(key -> modelMap.put(humpToLine(key), map.get(key)));
        }
        return modelMap;
    }

    public static JSONObject getHumpKeyMap(HashMap<String, Object> map) {
        JSONObject modelMap = new JSONObject();
        Set<String> strings = map.keySet();
        strings.forEach(key -> {
            modelMap.put(lineToHump(key), map.get(key));
        });
        return modelMap;
    }

    public static String lineToHump(String str) {
        Matcher matcher = patternLineToHump.matcher(str.toLowerCase());
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    public static String humpToLine(String str) {
        Matcher matcher = patternHumpToLine.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    public static Boolean isFieldExist(Class<?> clazz, String... columns) {
        for (String column : columns) {
            try {
                boolean result = clazz.getDeclaredField(column).getName().equals(column);
                if (!result) {
                    return false;
                }
            } catch (NoSuchFieldException e) {
                return false;
            }
        }
        return true;
    }

    public static <T> String getSortParams(Class<T> type,  String humpParams) {
        final StringBuffer stringBuffer = new StringBuffer();
        Arrays.asList(humpParams.split(",")).forEach((param -> {
            String lineParam = humpToLine(param);
            Field[] declaredFields = type.getDeclaredFields();
            if (Arrays.stream(declaredFields).anyMatch(field -> field.getName().equals(param))){
                stringBuffer.append(lineParam).append(",");
            }
        }));
        stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        return stringBuffer.toString();
    }

    public static <T> JSONObject getEqOrLikeMap(Class<T> type, Map<String, Object> eqOrLikeMap, String... excludeFields) {
        final JSONObject jsonObject = new JSONObject();
        eqOrLikeMap.forEach(((param,value) -> {
            if (value != null && value != "" && !Arrays.asList(excludeFields).contains(param)) {
                String lineParam = humpToLine(param);
                Field[] declaredFields = type.getDeclaredFields();
                if (Arrays.stream(declaredFields).anyMatch(field -> field.getName().equals(param))){
                    jsonObject.put(lineParam, eqOrLikeMap.get(param));
                }
            }
        }));
        return jsonObject;
    }

    public static <T> Map<String, List<String>> getInMap(Class<T> type, Map<String, Object> inMap, String... excludeFields) {
        final Map<String, List<String>> jsonObject = new HashMap<>();
        inMap.forEach((param,value) -> {
            if (value != null && value != "" && !Arrays.asList(excludeFields).contains(param)){
                String lineParam = humpToLine(param);
                Field[] declaredFields = type.getDeclaredFields();
                if (Arrays.stream(declaredFields).anyMatch(field -> field.getName().equals(param))){
                    try {
                        List<String> items = JSON.parseArray(JSON.toJSONString(value),String.class);
                        jsonObject.put(lineParam, items);
                    }catch (Exception ignored){}
                }
            }
        });
        return jsonObject;
    }
}